#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "types.h"
#include "defs.h"
#include "parser.h"
#include "lexer.h"
#include "runtime.h"

#define ASSERT(fmt,msg...) {printf("Parser message:");printf(fmt,##msg);exit(EXIT_FAILURE);}

enum var_type
str2vartype (char * str) {
    if (strcmp (str, "i8")==0) {
        return VAR_I8;
    }
    if (strcmp (str, "i16")==0) {
        return VAR_I16;
    }
    if (strcmp (str, "i32")==0) {
        return VAR_I32;
    }
    if (strcmp (str, "i64")==0) {
        return VAR_I64;
    }
    if (strcmp (str, "u8")==0) {
        return VAR_U8;
    }
    if (strcmp (str, "u16")==0) {
        return VAR_U16;
    }
    if (strcmp (str, "u32")==0) {
        return VAR_U32;
    }
    if (strcmp (str, "u64")==0) {
        return VAR_U64;
    }
    if (strcmp (str, "str")==0) {
        return VAR_STR;
    }
    if (strcmp (str, "space")==0) {
        return VAR_SPACE;
    }
    return VAR_INVALID;
}

enum reg_nm
str2reg (char * str) {
    if (strcmp (str, "a0") == 0) {
        return X_A0;
    }
    if (strcmp (str, "a1") == 0) {
        return X_A1;
    }
    if (strcmp (str, "a2") == 0) {
        return X_A2;
    }
    if (strcmp (str, "a3") == 0) {
        return X_A3;
    }
    if (strcmp (str, "t0") == 0) {
        return X_T0;
    }
    if (strcmp (str, "t1") == 0) {
        return X_T1;
    }
    if (strcmp (str, "t2") == 0) {
        return X_T2;
    }
    if (strcmp (str, "t3") == 0) {
        return X_T3;
    }
    if (strcmp (str, "t4") == 0) {
        return X_T4;
    }
    if (strcmp (str, "t5") == 0) {
        return X_T5;
    }
    if (strcmp (str, "t6") == 0) {
        return X_T6;
    }
    if (strcmp (str, "t7") == 0) {
        return X_T7;
    }
    return X_INVALID;
}

enum rtc_type
str2rtc (char * str) {
    if (strcmp (str, "begin") == 0) {
        return RTC_BEGIN;
    }
    if (strcmp (str, "end") == 0) {
        return RTC_END;
    }
    if (strcmp (str, "jit") == 0) {
        return RTC_JIT;
    }
    if (strcmp (str, "rt") == 0) {
        return RTC_RT;
    }
     return X_INVALID;
}

/* 时间有限,只能用最简单的方式实现了 */
struct syntaxlist *
parse (struct token * tk) {
    struct syntaxlist * stls;
    struct syntaxelem * ste;
    stls = (struct syntaxlist *) malloc (sizeof (struct syntaxlist));
    if (stls == NULL) goto error;
    bzero (stls, sizeof (struct syntaxlist));
    struct token * tkp;
    tkp = tk;
    while (tkp && tkp->type != TK_END) {
        ste = &(stls->ste[stls->sz]);
        switch (tkp->type) {
            case TK_RTC : {
                ste->type = SYN_RTC;
                if((ste->synt.rtc.type = str2rtc(tkp->str)) == RTC_INVALID)
                    ASSERT ("错误的运行时控制,行:%u\n", tkp->ln);
                goto parsed;
            }
            case TK_FUNC : {
                ste->type = SYN_FUNC;
                ste->synt.func.name = tkp->str;
                goto parsed;
            }
            case TK_LBL : {
                ste->type = SYN_LBL;
                ste->synt.lbl.name = tkp->str;
                goto parsed;
            }
            case TK_INS : {
                if (strcmp(tkp->str,"var") == 0) {
                    ste->type = SYN_VAR;
                    tkp = tkp->next;
                    ste->synt.var.name = tkp->str;
                    // tkp = tkp->next;
                } else if (strcmp (tkp->str, "asgn") == 0) {
                    ste->type = SYN_INS;
                    ste->synt.ins.type = INS_ASGN;
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_VAR) ASSERT ("指令asgn附近有语法错误,行:%u\n",tkp->ln);
                    ste->synt.ins.varname = tkp->str;
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_COMMA) ASSERT ("指令asgn附近有语法错误,行:%u\n",tkp->ln);
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_TYPE) ASSERT ("指令asgn附近有语法错误,行:%u\n",tkp->ln);
                    if((ste->synt.ins.vartype = str2vartype (tkp->str)) == VAR_INVALID) 
                        ASSERT ("指令asgn附近有语法错误,行:%u\n",tkp->ln);
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_COMMA) ASSERT ("指令asgn附近有语法错误,行:%u\n",tkp->ln);
                    tkp = tkp->next;
                    if (!tkp || (tkp->type != TK_IMM &&  tkp->type != TK_STR)) ASSERT ("指令asgn附近有语法错误,行:%u\n",tkp->ln);
                    ste->synt.ins.imm = tkp->num;
                    ste->synt.ins.str = tkp->str;
                    // 下一项应该是TK_NEXT
                } else if (strcmp (tkp->str, "cast") == 0) {
                    ste->type = SYN_INS;
                    ste->synt.ins.type = INS_CAST;
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_VAR) ASSERT ("指令cast附近有语法错误,行:%u\n",tkp->ln);
                    ste->synt.ins.varname = tkp->str;
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_COMMA) ASSERT ("指令cast附近有语法错误,行:%u\n",tkp->ln);
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_TYPE) ASSERT ("指令cast附近有语法错误,行:%u\n",tkp->ln);
                    if ((ste->synt.ins.vartype = str2vartype(tkp->str)) == VAR_INVALID)
                        ASSERT ("指令cast附近有语法错误,行:%u\n",tkp->ln);
                    // 下一项应该是TK_NEXT
                } else if (strcmp (tkp->str, "li") == 0) {
                    ste->type = SYN_INS;
                    ste->synt.ins.type = INS_LI;
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_REG) ASSERT ("指令li附近有语法错误,行:%u\n",tkp->ln);
                    if((ste->synt.ins.rd = str2reg (tkp->str)) == X_INVALID)
                        ASSERT ("指令li附近有语法错误,行:%u\n",tkp->ln);
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_COMMA) ASSERT ("指令li附近有语法错误,行:%u\n",tkp->ln);
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_IMM) ASSERT ("指令li附近有语法错误,行:%u\n",tkp->ln);
                    ste->synt.ins.imm = tkp->num;
                    // 下一项应该是TK_NEXT
                } else if (strcmp (tkp->str, "ld") == 0) {
                    ste->type = SYN_INS;
                    ste->synt.ins.type = INS_LD;
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_REG) ASSERT ("指令ld附近有语法错误,行:%u\n",tkp->ln);
                    if((ste->synt.ins.rd = str2reg (tkp->str)) == X_INVALID)
                        ASSERT ("指令ld附近有语法错误");
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_COMMA) ASSERT ("指令ld附近有语法错误,行:%u\n",tkp->ln);
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_VAR) ASSERT ("指令ld附近有语法错误,行:%u\n",tkp->ln);
                    ste->synt.ins.varname = tkp->str;
                    // 下一项应该是TK_NEXT
                } else if (strcmp (tkp->str, "addi") == 0) {
                    ste->type = SYN_INS;
                    ste->synt.ins.type = INS_ADDI;
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_REG) ASSERT ("指令addi附近有语法错误,行:%u\n",tkp->ln);
                    if((ste->synt.ins.rd = str2reg (tkp->str)) == X_INVALID)
                        ASSERT ("指令addi附近有语法错误");
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_COMMA) ASSERT ("指令addi附近有语法错误,行:%u\n",tkp->ln);
                    tkp = tkp->next;
                     if (!tkp || tkp->type != TK_REG) ASSERT ("指令addi附近有语法错误,行:%u\n",tkp->ln);
                    if((ste->synt.ins.rs1 = str2reg (tkp->str)) == X_INVALID)
                        ASSERT ("指令addi附近有语法错误");
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_COMMA) ASSERT ("指令addi附近有语法错误,行:%u\n",tkp->ln);
                    tkp = tkp->next;
                    if (!tkp || tkp->type != TK_IMM) ASSERT ("指令addi附近有语法错误,行:%u\n",tkp->ln);
                    ste->synt.ins.imm = tkp->num;
                } else if (strcmp (tkp->str, "ecall") == 0) {
                    ste->type = SYN_INS;
                    ste->synt.ins.type = INS_ECALL;
                } else if (strcmp (tkp->str, "ret") == 0) {
                    ste->type = SYN_INS;
                    ste->synt.ins.type = INS_RET;
                } else {
                    break;
                }
                goto parsed;
            }
            case TK_VAR:
            case TK_TYPE:
            case TK_REG:
            case TK_IMM:
            case TK_STR:
            case TK_COMMA:
            case TK_NEXT:
            case TK_END:
            case TK_INSVAR:
            break;
        }
        ASSERT ("不受支持的标识符:%s,行:%u\n", tkp->str, tkp->ln);
        parsed:
        if (tkp->next == NULL) ASSERT ("缺少终止符TK_END\n");
        tkp = tkp->next;
        stls->sz++;
        if (tkp->type == TK_END) break;
        if (tkp->type != TK_NEXT) ASSERT ("存在多余字符\'%s\',行:%u\n",tkp->str,tkp->ln);
        if (stls->sz >= MAX_NRSTELEM)
            ASSERT ("指令过多");
        tkp = tkp->next;
    }
    return stls;
    error:
    free (stls);
    return NULL;
}

struct syntaxlist *
checksyntax (struct syntaxlist * stls) {
    uint bg, ed;
    bg = ed = 0;
    struct syntaxelem * stp = stls->ste;
    while (stp != NULL) {
        if (bg && ed)
            break;
        if (stp->synt.rtc.type == RTC_BEGIN) {
            if (bg == 1) 
                ASSERT ("存在语义错误\n");
            bg = 1;
        }
        if (stp->synt.rtc.type == RTC_END) {
            if (bg == 0)
                ASSERT ("存在语义错误\n");
            ed = 1;
            break;
        }
    }
    if (!(bg && ed)) ASSERT ("存在语义错误\n");
    return stls;
}

#define MAX_NRHMAPHD 1024 //  本文件所使用哈希表头长度

struct hashnode {
    char * key;
    union {
        uint64 data;
        void* addr;
    } value;
    struct hashnode * next;
};

struct hashnode heapvarmap[MAX_NRHMAPHD]; // 堆变量哈希表, value为指向struct var的指针value.addr
struct hashnode stackvarmap[MAX_NRHMAPHD]; // 栈变量哈希表, value为指向struct var的指针value.addr !每经过一次ret释放一次
struct hashnode fnmap[MAX_NRHMAPHD]; // 函数名哈希表,value为函数起始地址(虚拟机PC),value.data
struct hashnode lblmap[MAX_NRHMAPHD]; // 局部标签哈希表,value为标签地址,value.data

uint
bkdrhash (char * str) {
    uint seed = 1313;
    uint hash = 0;
    while(*str)
    {
        hash = hash*seed + (*str++);
    }
    return hash%MAX_NRHMAPHD;
}

int
hashmap_init (struct hashnode hmap[]) {
    bzero (hmap, sizeof (struct hashnode) * MAX_NRHMAPHD);
    return SUCCESS;
}

int
hashmap_insert (struct hashnode hmap[], struct hashnode * node) {
    if (node == NULL) return ERROR;
    uint idx;
    struct hashnode *headptr;
    idx = bkdrhash(node->key);
    headptr = hmap+idx;
    node->next = headptr->next;
    headptr->next = node;
    return SUCCESS;
}

struct hashnode * // 未找到返回NULL
hashmap_find (struct hashnode hmap[], char * key) {
    uint idx;
    struct hashnode *headptr, * workptr;
    idx = bkdrhash (key);
    headptr = hmap + idx;
    workptr = headptr->next;
    while (workptr) {
        if (strcmp (workptr->key, key) == 0)
            return workptr;
        workptr = workptr->next;
    }
    return NULL;
}

int
hashmap_destory (struct hashnode hmap[]) {
    struct hashnode *headptr, * workptr, *tmptr;
    for (headptr = hmap; headptr-hmap != MAX_NRHMAPHD; headptr++) {
        workptr = headptr->next;
        headptr->next = NULL;
        while (workptr) {
            tmptr = workptr;
            workptr = workptr->next;
            free (tmptr);
        }
    }
    return SUCCESS;
}

#define MAX_ISTACKSZ 1024 // 最多存储128条指令
struct {
    struct ins * stack[MAX_ISTACKSZ];
    uint top;
} istack; // 可以预存指令

int
istack_clr () {
    istack.top = 0;
    return SUCCESS;
}

int
istack_push (struct ins * i) {
    if (istack.top == MAX_ISTACKSZ-1)
        return ERROR;
    istack.stack[istack.top++] = i;
    return SUCCESS;
}

struct ins * // 栈空pop NULL
istack_pop () {
    if (istack.top == 0)
        return NULL;
    return istack.stack[istack.top--];
}

struct textseg *
gettextseg (struct syntaxlist * stls, struct varh * vh) {
    struct textseg * ts;
    struct hashnode * newnode, *tmpnode;
    struct ins * tmpins;
    struct var * tmpvar;
    uint pc;
    ts = (struct textseg *) malloc (sizeof (struct textseg)); 
    if (ts == NULL) return NULL; // 内存不足
    bzero (ts, sizeof (struct textseg));
    struct syntaxelem *ste;
    struct {
        struct {
            uint inside; // 该语句是否在函数内?
            char * name; // 函数名
            uint call; // 首地址
            // uint ret; // 结尾地址
            uint varspace; // 解析到目前发现的变量大小
        } func;
        struct {
            uint fn_set; // 为下一条指令添加函数标签
            char * fn_name;
            uint lbl_set; // 为下一条指令添加局部标签
            char * lbl_name;
            uint rtc_set; // 为下一条指令添加运行时控制
            enum rtc_type rtc_type;
        } attr;
    } status;
    hashmap_init (heapvarmap);
    hashmap_init (stackvarmap);
    hashmap_init (fnmap);
    hashmap_init (lblmap);
    istack_clr ();
    bzero (&status, sizeof (status));
    #define clr_attr() {bzero (&status.attr,sizeof (status.attr));}
    #define clr_func() {bzero (&status.func,sizeof (status.func));}
    #define clr_status() {clr_attr;clr_func;}
    #define attr_setted (status.attr.fn_set || status.attr.lbl_set || status.attr.rtc_set)
    #define true 1
    #define false 0
    pc = 0;
    #define PC (pc)
    #define I (ts->insls[PC])
    #define S (ste->synt.ins)
    ste=stls->ste;
    while (ste<stls->ste+stls->sz &&ste->synt.rtc.type != RTC_BEGIN) ste++; // 寻找BEGIN标签
    if (ste == stls->ste+stls->sz) ASSERT ("无起始控制\n");
    ste++; // BEGIN下一条
    for (;ste<stls->ste+stls->sz;ste++) {
        // printf ("%d\n",ste->type);
        // getchar ();
        if (ste->type == SYN_RTC) { // 运行时控制
            if (ste->synt.rtc.type == RTC_END) {
                I.type = INS_END;
                I.flg |= F_INS_VALID;
                ts->end = PC;
                PC++;
                goto finish;
            }
            //printf ("RTC: %d\n", ste->synt.rtc.type);
            if (status.attr.rtc_set) ASSERT ("一条指令只允许一个运行时控制"); // 一条指令只允许一个RTC
            status.attr.rtc_type = ste->synt.rtc.type; // 设置rtc标签
            status.attr.rtc_set = true; // 打开rtc标签提示
        }
        if (ste->type == SYN_LBL) {
            if (!status.func.inside) ASSERT ("函数外局部标签");
            if (status.attr.lbl_set) ASSERT ("一条指令只允许一个局部标签"); // 一条指令只允许一个label
            status.attr.lbl_name = ste->synt.lbl.name; // 设置标签名
            status.attr.lbl_set = true; // 设置局部标签提示
        }
        if (ste->type == SYN_FUNC) { // 新函数
            if (status.func.inside) ASSERT ("上一函数未结束"); // ret指令置0
            if (status.attr.fn_set) ASSERT ("一条指令只允许一个函数声明");
            clr_func();
            status.func.varspace = 0; // 栈区空间清零
            status.attr.fn_name = ste->synt.func.name; // 缓存函数名
            status.attr.fn_set = true; // 设置函数标签提示
        }
        if (ste->type == SYN_VAR) { // 变量声明
            if (status.attr.fn_set || status.func.inside) { // 栈区变量 
               if (hashmap_find (stackvarmap, ste->synt.var.name) != NULL) // 重复声明
                    ASSERT ("重复声明局部变量");
                newnode = (struct hashnode *) malloc (sizeof (struct hashnode));
                tmpvar = (struct var *) malloc (sizeof (struct var));
                if (newnode == NULL || tmpvar == NULL) ASSERT ("内存不足");
                tmpvar->flg = F_VAR_VALID | F_VAR_STACK; // 声明为栈区变量
                tmpvar->stackoff = status.func.varspace; // 栈偏移为当前栈变量累计空间
                tmpvar->type = VAR_UNDEF;
                newnode->key = ste->synt.var.name; // 关联变量
                newnode->value.addr = tmpvar; // 设置var地址
                status.func.varspace += 8; //栈占用空间+8(统一用64位存储) 
                hashmap_insert (stackvarmap, newnode); // 将变量插入局部变量表
            } else { //堆区变量 
                if (hashmap_find (heapvarmap, ste->synt.var.name) != NULL) // 重复声明
                    ASSERT ("重复声明全局变量");
                newnode = (struct hashnode *) malloc (sizeof (struct hashnode));
                tmpvar = (struct var *) malloc (sizeof (struct var));
                if (newnode == NULL || tmpvar == NULL) ASSERT ("内存不足");
                tmpvar->flg = F_VAR_VALID | F_VAR_HEAP; // 声明为堆区变量
                void * hp = varalloc (vh,8); // 在堆中分配一个8字节的空间
                tmpvar->heapaddr = hp;
                tmpvar->type = VAR_UNDEF;
                newnode->key = ste->synt.var.name; // 关联变量
                newnode->value.addr = tmpvar; // 设置var地址
                hashmap_insert (heapvarmap, newnode); // 将变量插入全局变量表
            }
        }
        if (ste->type == SYN_INS) {
            // printf ("check \n");
            // fflush (stdout);
            bzero (ts->insls+PC, sizeof (struct ins)); // 清空代码段当前指令
            I.type = S.type; // 设置指令类型
            I.flg = 0;
            if (status.attr.fn_set) { // 有fn标记
                I.flg |= F_INS_FUNC; // 添加FUNC标记
                status.func.inside = true; // 更新当前指令为函数内
                status.func.name = status.attr.fn_name; // 更新当前函数名
                status.func.call = PC; // 更新当前函数起始地址
                I.func = status.attr.fn_name;
                newnode = (struct hashnode *) malloc (sizeof (struct hashnode));
                if (newnode == NULL) ASSERT ("内存不足");
                newnode->key = status.attr.fn_name;
                newnode->value.data = PC;
                hashmap_insert (fnmap, newnode);
            }
            if (!status.func.inside) ASSERT ("不允许在函数外使用指令");
            if (status.attr.lbl_set) { // 有lbl标记
                I.flg |= F_INS_LBL; // 添加lbl标记
                I.lbl = status.attr.lbl_name;
                newnode = (struct hashnode *) malloc (sizeof (struct hashnode));
                if (newnode == NULL) ASSERT ("内存不足");
                newnode->key = status.attr.lbl_name;
                newnode->value.data = PC;
                hashmap_insert (lblmap, newnode);
            }
            if (status.attr.rtc_set) { // 有rtc标记
                I.flg |= F_INS_RTC;
                I.rtc = status.attr.rtc_type; // 设置RTC
            }
            switch (S.type) {
                case INS_ASGN : {
                    tmpnode = hashmap_find (stackvarmap, S.varname);
                    if (tmpnode == NULL)
                        tmpnode = hashmap_find (heapvarmap, S.varname);
                    if (tmpnode == NULL) ASSERT ("变量不存在");
                    tmpvar = tmpnode->value.addr;
                    I.v = tmpvar;
                    I.asgn.type = S.vartype;
                    I.asgn.space = S.imm;
                    I.asgn.str = S.str;
                    I.asgn.imm = S.imm;
                    break;
                }
                case INS_CAST : {
                    tmpnode = hashmap_find (stackvarmap, S.varname);
                    if (tmpnode == NULL)
                        tmpnode = hashmap_find (heapvarmap, S.varname);
                    if (tmpnode == NULL) ASSERT ("变量不存在");
                    tmpvar = tmpnode->value.addr;
                    I.casttype = S.vartype;
                    I.v = tmpvar;
                    break;
                }
                case INS_LI : {
                    I.imm = S.imm;
                    I.r0 = S.rd;
                    break;
                }
                case INS_ADDI : {
                    I.imm = S.imm;
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    break;
                }
                case INS_SLTI : {
                    I.imm = S.imm;
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    break;
                }
                case INS_SLTIU : {
                    I.imm = S.imm;
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    break;
                }
                case INS_XORI : {
                    I.imm = S.imm;
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    break;
                }
                case INS_ORI : {
                    I.imm = S.imm;
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    break;
                }
                case INS_ANDI : {
                    I.imm = S.imm;
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    break;
                }
                case INS_SLLI : {
                    I.imm = S.imm;
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    break;
                }
                case INS_SRLI : {
                    I.imm = S.imm;
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    break;
                }
                case INS_SRAI : {
                    I.imm = S.imm;
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    break;
                }
                case INS_ADD : {
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    I.r2 = S.rs2;
                    break;
                }
                case INS_SUB : {
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    I.r2 = S.rs2;
                    break;
                }
                case INS_SLL : {
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    I.r2 = S.rs2;
                    break;
                }
                case INS_SLT : {
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    I.r2 = S.rs2;
                    break;
                }
                case INS_SLTU : {
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    I.r2 = S.rs2;
                    break;
                }
                case INS_XOR : {
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    I.r2 = S.rs2;
                    break;
                }
                case INS_SRL : {
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    I.r2 = S.rs2;
                    break;
                }
                case INS_SRA : {
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    I.r2 = S.rs2;
                    break;
                }
                case INS_OR : {
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    I.r2 = S.rs2;
                    break;
                }
                case INS_AND : {
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    I.r2 = S.rs2;
                    break;
                }
                case INS_NOT : {
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    I.r2 = S.rs2;
                    break;
                }
                case INS_LDI : {
                    tmpnode = hashmap_find (stackvarmap, S.varname);
                    if (tmpnode == NULL)
                        tmpnode = hashmap_find (heapvarmap, S.varname);
                    if (tmpnode == NULL) ASSERT ("变量不存在");
                    tmpvar = tmpnode->value.addr;
                    I.iadr = S.vartype; // 间址类型
                    I.v = tmpvar;
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    break;
                }
                case INS_STI : {
                    tmpnode = hashmap_find (stackvarmap, S.varname);
                    if (tmpnode == NULL)
                        tmpnode = hashmap_find (heapvarmap, S.varname);
                    if (tmpnode == NULL) ASSERT ("变量不存在");
                    tmpvar = tmpnode->value.addr;
                    I.iadr = S.vartype; // 间址类型
                    I.v = tmpvar;
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    break;
                }
                case INS_LD : {
                    tmpnode = hashmap_find (stackvarmap, S.varname);
                    if (tmpnode == NULL)
                        tmpnode = hashmap_find (heapvarmap, S.varname);
                    if (tmpnode == NULL) ASSERT ("变量不存在");
                    tmpvar = tmpnode->value.addr;
                    I.v = tmpvar;
                    I.r0 = S.rd;
                    break;
                }
                case INS_ST : {
                    tmpnode = hashmap_find (stackvarmap, S.varname);
                    if (tmpnode == NULL)
                        tmpnode = hashmap_find (heapvarmap, S.varname);
                    if (tmpnode == NULL) ASSERT ("变量不存在");
                    tmpvar = tmpnode->value.addr;
                    I.v = tmpvar;
                    I.r0 = S.rd;
                    break;
                }
                case INS_CALL : {
                    tmpnode = hashmap_find (fnmap, S.func);
                    if (tmpnode == NULL) ASSERT ("函数不存在");
                    I.j = tmpnode->value.data;
                    I.varspace = status.func.varspace; // 当前栈空间
                    break;
                }
                case INS_RET : {
                    I.varspace = status.func.varspace;
                    while ((tmpins = istack_pop ()) != NULL) {
                        if (!(tmpins->flg & F_INS_VALID) || 
                        !(tmpins->type >= INS_B && tmpins->type <= INS_BGE))
                            ASSERT ("解析器内部错误");
                        tmpnode = hashmap_find (lblmap, tmpins->lbl);
                        if (tmpnode == NULL) ASSERT ("局部标签不存在");
                        tmpins->j = tmpnode->value.data;
                    }
                    istack_clr ();
                    hashmap_destory (stackvarmap); // 销毁局部变量哈希表
                    hashmap_destory (lblmap); // 销毁局部标签
                    clr_func ();
                    break;
                }
                case INS_MV : {
                    I.r0 = S.rd;
                    I.r1 = S.rs1;
                    break;
                }
                case INS_B : {
                    tmpnode = hashmap_find (lblmap, S.lbl);
                    if (tmpnode == NULL) {
                        istack_push (&I);
                    } else {
                        I.j = tmpnode->value.data;
                    }
                    I.lbl = S.lbl;
                    break;
                }
                case INS_BEQ : {
                    tmpnode = hashmap_find (lblmap, S.lbl);
                    if (tmpnode == NULL) {
                        istack_push (&I);
                    } else {
                        I.j = tmpnode->value.data;
                    }
                    I.lbl = S.lbl;
                    I.j = tmpnode->value.data;
                    break;
                }
                case INS_BNE : {
                    tmpnode = hashmap_find (lblmap, S.lbl);
                    if (tmpnode == NULL) {
                        istack_push (&I);
                    } else {
                        I.j = tmpnode->value.data;
                    }
                    I.lbl = S.lbl;
                    I.j = tmpnode->value.data;
                    break;
                }
                case INS_BLT : {
                    tmpnode = hashmap_find (lblmap, S.lbl);
                    if (tmpnode == NULL) {
                        istack_push (&I);
                    } else {
                        I.j = tmpnode->value.data;
                    }
                    I.lbl = S.lbl;
                    I.j = tmpnode->value.data;
                    break;
                }
                case INS_BGE : {
                    tmpnode = hashmap_find (lblmap, S.lbl);
                    if (tmpnode == NULL) {
                        istack_push (&I);
                    } else {
                        I.j = tmpnode->value.data;
                    }
                    I.lbl = S.lbl;
                    I.j = tmpnode->value.data;
                    break;
                }
                case INS_ECALL : {
                    I.type = INS_ECALL;
                    break;
                }
                default :  {
                    //printf ();
                    ASSERT ("解析错误");
                    return NULL;
                }
            }
            I.flg |= F_INS_VALID;
            clr_attr (); // 清除标记
            PC++;
        }
    }
    finish:
    ts->sz = PC;
    hashmap_destory (heapvarmap);
    hashmap_destory (stackvarmap);
    hashmap_destory (fnmap);
    hashmap_destory (lblmap);
    return ts;
}